package socket

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"io"
	"log"
	"net/http"
	"os"
	"sync"
	"time"
	Asr "xiaozhi/asr_server"
	"xiaozhi/utils"
)

// ClientMessage 定义客户端消息结构
type ClientMessage struct {
	SessionID    string       `json:"session_id"`
	Type         string       `json:"type"`
	Version      int          `json:"version"`
	Transport    string       `json:"transport"`
	ResponseMode string       `json:"response_mode"`
	AudioParams  AudioParams  `json:"audio_params"`
	State        string       `json:"state"`
	Mode         string       `json:"mode"`
	Text         string       `json:"text"`
	Descriptors  []Descriptor `json:"descriptors"`
	States       interface{}  `json:"states"`
	Emotion      string       `json:"emotion"`
	Reason       string       `json:"reason"`
}

type AudioParams struct {
	Format        string `json:"format"`
	SampleRate    int    `json:"sample_rate"`
	Channels      int    `json:"channels"`
	FrameDuration int    `json:"frame_duration"`
}

type Descriptor struct {
	Name        string              `json:"name"`
	Description string              `json:"description"`
	Properties  map[string]Property `json:"properties"`
	Methods     map[string]Method   `json:"methods"`
}

type Property struct {
	Description string `json:"description"`
	Type        string `json:"type"`
}

type Method struct {
	Description string               `json:"description"`
	Parameters  map[string]Parameter `json:"parameters"`
}

type Parameter struct {
	Description string `json:"description"`
	Type        string `json:"type"`
}

// ServerResponse 定义服务端应答消息结构
type ServerResponse struct {
	SessionID string `json:"session_id,omitempty"`
	Type      string `json:"type"`
	State     string `json:"state,omitempty"`
	Text      string `json:"text,omitempty"`
	Emotion   string `json:"emotion,omitempty"`
	Error     string `json:"error,omitempty"`
	States    string
	Mode      string
}

// Client 客户端结构
type Client struct {
	conn *websocket.Conn
}

// 客户端映射表
var clients = make(map[string]*Client)
var mutex = &sync.Mutex{}

// pcmStream allows faiface to play PCM directly
//type pcmStream struct {
//	r   io.Reader
//	f   beep.Format
//	buf []byte
//	len int
//	pos int
//	err error
//}
//
//func (s *pcmStream) Err() error { return s.err }
//
//func (s *pcmStream) Stream(samples [][2]float64) (n int, ok bool) {
//	width := s.f.Width()
//	// if there's not enough data for a full sample, get more
//	if size := s.len - s.pos; size < width {
//		// if there's a partial sample, move it to the beginning of the buffer
//		if size != 0 {
//			copy(s.buf, s.buf[s.pos:s.len])
//		}
//		s.len = size
//		s.pos = 0
//		// refill the buffer
//		nbytes, err := s.r.Read(s.buf[s.len:])
//		if err != nil {
//			if err != io.EOF {
//				s.err = err
//			}
//			return n, false
//		}
//		s.len += nbytes
//	}
//	// decode as many samples as we can
//	for n < len(samples) && s.len-s.pos >= width {
//		samples[n], _ = s.f.DecodeSigned(s.buf[s.pos:])
//		n++
//		s.pos += width
//	}
//	return n, true
//}
//
//type opusReader struct {
//	oggFile     *oggreader.OggReader
//	opusDecoder opus.Decoder
//
//	decodeBuffer       []byte
//	decodeBufferOffset int
//
//	segmentBuffer [][]byte
//}
//
//func (o *opusReader) Read(p []byte) (n int, err error) {
//	if o.decodeBufferOffset == 0 || o.decodeBufferOffset >= len(o.decodeBuffer) {
//		if len(o.segmentBuffer) == 0 {
//			for {
//				o.segmentBuffer, _, err = o.oggFile.ParseNextPage()
//				if err != nil {
//					return 0, err
//				} else if bytes.HasPrefix(o.segmentBuffer[0], []byte("OpusTags")) {
//					continue
//				}
//
//				break
//			}
//		}
//
//		var segment []byte
//		segment, o.segmentBuffer = o.segmentBuffer[0], o.segmentBuffer[1:]
//
//		o.decodeBufferOffset = 0
//		if _, _, err = o.opusDecoder.Decode(segment, o.decodeBuffer); err != nil {
//			panic(err)
//		}
//	}
//
//	n = copy(p, o.decodeBuffer[o.decodeBufferOffset:])
//	o.decodeBufferOffset += n
//	return n, nil
//}

// HandleConnections WebSocket 处理函数
func HandleConnections(w http.ResponseWriter, r *http.Request) {
	// 验证必要的 headers
	authHeader := r.Header.Get("Authorization")
	protocolVersion := r.Header.Get("Protocol-Version")
	deviceId := r.Header.Get("Device-Id")
	clientId := r.Header.Get("Client-Id")

	if authHeader == "" {
		log.Printf("Missing Authorization header")
		//http.Error(w, "Missing Authorization header", http.StatusBadRequest)
		//return
	}
	if protocolVersion != "1" {
		log.Printf("Invalid or missing Protocol-Version header")
		//http.Error(w, "Invalid or missing Protocol-Version header", http.StatusBadRequest)
		//return
	}
	if deviceId == "" {
		log.Printf("Missing Device-Id header")
		//http.Error(w, "Missing Device-Id header", http.StatusBadRequest)
	}
	// 生成会话ID
	sessionID := clientId
	if clientId == "" {
		sessionID = generateSessionID()
		log.Printf("Missing Client-Id header")
		//http.Error(w, "Missing Client-Id header", http.StatusBadRequest)
		//return
	}
	fmt.Printf("Authorization: %s, Protocol-Version: %s, Device-Id: %s, Client-Id: %s\n", authHeader, protocolVersion, deviceId, clientId)
	// 升级 HTTP 连接为 WebSocket 连接
	upgrade := websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	ws, err := upgrade.Upgrade(w, r, nil)
	if err != nil {
		log.Printf("Failed to upgrade to WebSocket: %v", err)
		return
	}
	defer func(ws *websocket.Conn) {
		err := ws.Close()
		if err != nil {
			log.Printf("Error closing WebSocket: %v", err)
		}
	}(ws)

	// 创建一个新客户端
	client := &Client{conn: ws}
	// 接收客户端的初始化消息
	var msg ClientMessage
	err = readMessage(ws, &msg)
	if err != nil {
		log.Printf("Failed to read initial message: %v", err)
		return
	}

	// 将客户端添加到映射表中
	mutex.Lock()
	clients[sessionID] = client
	mutex.Unlock()

	// 处理初始化消息
	switch msg.Type {
	case "hello":
		handleHello(client, msg, sessionID)
	case "abort":
		handleAbort(client, msg, sessionID)
	case "tts":
		handleTTS(client, msg, sessionID)
	case "listen":
		handleListen(client, msg, sessionID)
	case "iot":
		handleIoT(client, msg, sessionID)
	default:
		log.Printf("Unknown message type: %s", msg.Type)
	}

	// 标志表示是否接收到 hello 消息
	//receivingAudio := false

	// 创建一个通道用于传递音频数据
	audioChan := make(chan []byte, 10)
	stream := &utils.PCMStream{}
	// 启动 ASR 服务
	asr := Asr.Asr{}
	asr.Init()

	//var samples []int16
	//tempAudio := make([]byte, 960)
	// 持续监听客户端消息
	for {
		msgType, msgData, err := ws.NextReader()
		if err != nil {
			log.Printf("Failed to read message: %v", err)
			break
		}
		data, err := io.ReadAll(msgData)

		switch msgType {
		case websocket.TextMessage:
			//if !receivingAudio {
			// 处理文本消息
			//err = json.Unmarshal(msgData, &msg)
			if err != nil {
				log.Printf("Failed to unmarshal JSON: %v", err)
				// 发送错误响应给客户端
				sendErrorResponse(ws, "Invalid JSON format")
				continue
			}
			fmt.Println("Json数据: ", string(data))
			// 处理不同类型的消息
			switch msg.Type {
			case "hello":
				handleHello(client, msg, sessionID)
			case "abort":
				handleAbort(client, msg, sessionID)
			case "tts":
				handleTTS(client, msg, sessionID)
			case "listen":
				handleListen(client, msg, sessionID)
				//receivingAudio = true // 设置标志表示接下来的消息是语音数据
			case "iot":
				handleIoT(client, msg, sessionID)
			default:
				log.Printf("Unknown message type: %s", msg.Type)
			}
			//} else {
			//	// 如果已经接收到 hello 消息，则忽略文本消息
			//	log.Printf("Ignoring text message after hello1: %s", string(msgData))
			//}
		case websocket.BinaryMessage:
			fmt.Println("BinaryData: ", string(data))

			// 采样率、通道数和帧长
			//sampleRate := 16000
			//channels := 1
			//frameDuration := 60 // ms

			// 每帧的样本数
			//samplesPerFrame := sampleRate * frameDuration / 1000
			// 每帧的字节数
			//bytesPerFrame := samplesPerFrame * 2 * channels

			// 处理音频流，分割成帧

			//asr.OnMessage(samples)
			//isSte, _ := utils.IsAudio(msgData)
			//fmt.Printf("isSte:%v, types:%v", isSte, types)
			//if isSte {
			//	log.Printf("Received binary message: %v", msgData)
			//	// 处理二进制数据
			//	// 将音频数据传递给 ASR 服务
			//	tempAudio = append(tempAudio, msgData...)
			//byteData, _ := io.ReadAll(msgData)
			//const bufferSize = 1000      // 自定义缓冲区大小，1KB绰绰有余
			//var frameSizeMs int16 = 60 // 如果不确定，可选用60 ms。
			//frameSize := 1 * frameSizeMs * 16000 / 1000
			if len(data) > 1 {
				stream.Append(data)
				//if utils.IsPCM(msgData) {
				//	frames := utils.ProcessAudioStream(msgData, int(bytesPerFrame))
				//	err := utils.SaveFramesToPCMFile("test.wav", frames)
				//	if err != nil {
				//		return
				//	}
				//}

				test, err := os.OpenFile("test.wav", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
				if err != nil {
					log.Fatal(err)
				}
				_, err = test.Write(data)
				if err != nil {
					log.Printf("Failed to write audio data: %v", err)
					return
				}
				test.Close()
			} else {

				//completePCMData := stream.GetPCMData()
				////fmt.Println(msgData)
				//test, err := os.OpenFile("test.wav", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
				//if err != nil {
				//	log.Fatal(err)
				//}
				//_, err = test.Write(completePCMData)
				//if err != nil {
				//	log.Printf("Failed to write audio data: %v", err)
				//	return
				//}
				//test.Close()
				//
				//pcm := make([]byte, 960)
				//enc := opus.NewDecoder()
				//// 检查帧大小。如果您信任输入，则无需这样做。
				//n, _, err := enc.Decode(completePCMData, pcm)
				//if err != nil {
				//	log.Printf("Failed to decode audio: %v", err)
				//	//continue
				//}
				//pcm = pcm[:n*2]
				////big := utils.Int16sToBytesBigEndian(pcm)
				//asr.OnMessage(completePCMData)
			}

		default:
			log.Printf("Unknown message type: %d", msgType)
		}
	}

	// 关闭音频通道
	close(audioChan)
	// 从映射表中删除客户端
	mutex.Lock()
	delete(clients, sessionID)
	mutex.Unlock()
}

// 读取消息
func readMessage(ws *websocket.Conn, msg *ClientMessage) error {
	_, msgData, err := ws.ReadMessage()
	if err != nil {
		return err
	}

	// 记录接收到的原始数据
	log.Printf("Received raw message: %s", string(msgData))

	// 尝试解析JSON数据
	err = json.Unmarshal(msgData, msg)
	if err != nil {
		log.Printf("Failed to unmarshal JSON: %v", err)
		// 发送错误响应给客户端
		sendErrorResponse(ws, "Invalid JSON format")
		return err
	}

	return nil
}

// 发送错误响应
func sendErrorResponse(ws *websocket.Conn, errorMessage string) {
	response := ServerResponse{
		Type:  "error",
		Error: errorMessage,
	}
	err := ws.WriteJSON(response)
	if err != nil {
		log.Printf("Failed to send error response: %v", err)
	}
}

// 生成会话ID
func generateSessionID() string {
	return fmt.Sprintf("session-%d", time.Now().UnixNano())
}

// 处理Hello消息
func handleHello(client *Client, msg ClientMessage, sessionID string) {
	// 构造应答消息
	response := ClientMessage{
		Type:      "hello",
		Transport: "websocket",
		AudioParams: AudioParams{
			SampleRate: 16000,
		},
		SessionID: sessionID,
	}

	// 发送应答消息
	err := client.conn.WriteJSON(response)
	if err != nil {
		log.Printf("Failed to send hello response: %v", err)
	}
}

// 处理abort消息
func handleAbort(client *Client, msg ClientMessage, sessionID string) {
	// 构造应答消息
	response := ServerResponse{
		Type:  "abort",
		Error: "Aborted",
	}

	// 发送应答消息
	err := client.conn.WriteJSON(response)
	if err != nil {
		log.Printf("Failed to send abort response: %v", err)
	}
}

// 处理TTS消息
func handleTTS(client *Client, msg ClientMessage, sessionID string) {
	// 构造应答消息
	response := ServerResponse{
		Type:  "tts",
		State: msg.State,
		Text:  msg.Text,
	}

	// 发送应答消息
	err := client.conn.WriteJSON(response)
	if err != nil {
		log.Printf("Failed to send tts response: %v", err)
	}
}

// 处理Listen消息
func handleListen(client *Client, msg ClientMessage, sessionID string) {
	// 构造应答消息
	//response := ClientMessage{
	//	Type:      "hello",
	//	Transport: msg.Transport,
	//	AudioParams: AudioParams{
	//		SampleRate: 16000,
	//	},
	//}

	// 发送应答消息
	//err := client.conn.WriteJSON(response)
	//if err != nil {
	//	log.Printf("Failed to send listen response: %v", err)
	//}

	// 发送开始监听消息
	startListenResponse := ServerResponse{
		Type:      "listen",
		State:     "stop",
		Mode:      "auto",
		SessionID: sessionID,
	}
	err := client.conn.WriteJSON(startListenResponse)
	if err != nil {
		log.Printf("Failed to send start listen response: %v", err)
	}
}

// 处理IoT消息
func handleIoT(client *Client, msg ClientMessage, sessionID string) {
	// 构造应答消息
	response := ServerResponse{
		Type:      "iot",
		States:    fmt.Sprintf("Received descriptors: %+v", msg.Descriptors),
		SessionID: sessionID,
	}

	// 检查关键字段是否为空
	if msg.SessionID == "" {
		response.Error = "session_id is empty"
	} else if msg.Type != "iot" {
		response.Error = "invalid message type"
	}

	// 发送应答消息
	err := client.conn.WriteJSON(response)
	if err != nil {
		log.Printf("Failed to send iot response: %v", err)
	}
}

// 发送 listen 消息
func sendListenResponse(client *Client, sessionID string) {
	response := ServerResponse{
		SessionID: sessionID,
		Type:      "listen",
		State:     "stop",
	}

	// 发送应答消息
	err := client.conn.WriteJSON(response)
	if err != nil {
		log.Printf("Failed to send listen response: %v", err)
	}
}
